home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / USBSampleStorageDriver / StorageClassDriver / StorageClassShimDS.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  19.5 KB  |  667 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        StorageClassShimDS.c
  3.  
  4.     Contains:    USB Storage Class Shim Driver Services - 
  5.                 This file contains all functions related to providing driver services
  6.                 to USB UnitTable drivers.
  7.  
  8.     Version:    1.3
  9.  
  10.     Copyright:    © 1998-2000 by Apple Computer, Inc., all rights reserved.
  11. */
  12. #include <Appearance.h>
  13. #include <DriverServices.h>
  14. #include <Gestalt.h>
  15. #include <Resources.h>
  16. #include <TextUtils.h>
  17.  
  18. #include "StorageClassShimDS.h"
  19. #include "StorageClassShim.h"
  20.  
  21. #ifndef DIALOG_REZ_NUMBER
  22. #define DIALOG_REZ_NUMBER 128
  23. #endif
  24.  
  25. typedef struct ShimDialogStrings 
  26. {
  27.     Str255    string1;
  28.     Str255    string2;
  29.     Str255    string3;
  30. } ShimDialogStrings, *ShimDialogStringsPtr;
  31.  
  32. // These are the Head and Tail pointers for our DriverInfo Linked List.
  33. // This list handles associating USBDeviceRefs with UnitTable Driver refnums, so
  34. // Drivers can be removed from the UnitTable when the drive is removed.
  35. static DriverInfoPtr        DriverInfoHeadPtr;
  36. static DriverInfoPtr        DriverInfoTailPtr;
  37. static Boolean                gAppearanceIsPresent = false;
  38. static CFragConnectionID    appearLibID = 0;
  39.  
  40. // Static variables for the Dialog strings
  41. static ShimDialogStrings    EjectFloppyStrings;
  42. static ShimDialogStrings    EjectCartridgeStrings;
  43. static ShimDialogStrings    ReinsertFloppyStrings;
  44. static ShimDialogStrings    ReinsertCartridgeStrings;
  45. static ShimDialogStrings    ReattachDeviceStrings;
  46. static Str255                ReattachDeviceHardDiskString3;
  47. static ShimDialogStrings    CartridgeProtectedStrings;
  48. static NMUPP                gHandleDiskRemovedUPP = nil;
  49. static NMUPP                gDisplayNotificationDlogUPP = nil;
  50. static ModalFilterUPP        gEjectDialogFilterUPP = nil;
  51.  
  52. // Functions used by USBShim to load and release all dialog related resources
  53. static Boolean         LoadDialogResources( void );
  54. static Boolean         ReleaseDialogResources( void );
  55.  
  56. static OSStatus HandleStorageEvent( DriverRefNum drvrRefNum, UInt16 messageNumber );
  57. static Boolean IsAppearancePresent( void );
  58.  
  59. // Functions provided by the Shim for Unit Table drivers to use
  60. static void         InitializeDriverInfoStruct( void );
  61. static StorageClassShimDispatchTable    gShimDispatchTable = 
  62.                                             {    
  63.                                                 &HandleStorageEvent,
  64.                                                 &RemoveNotificationDialog
  65.                                             };
  66.  
  67.  
  68. // These are the prototypes for internal functions needed to perform our Driver Services
  69. // These will be used to create the needed UPPs
  70. static void HandleDiskWasRemovedEvent( NMRecPtr theNMRecPtr );
  71. static void ActualDisplayNotifcationDialog( NMRecPtr theNMRecPtr );
  72. static Boolean EjectDialogFilterProc(DialogPtr theDialog, EventRecord *theEvent, DialogItemIndex *itemHit);
  73.  
  74. // This routine is used to initialize the driver info structure
  75. Boolean InitializeStorageDriverServices( void )
  76. {
  77.     // Initialize DriverInfoHeadPtr 
  78.     DriverInfoHeadPtr = nil;    
  79.     DriverInfoTailPtr = nil;
  80.  
  81.     if ( gHandleDiskRemovedUPP == nil )
  82.     {
  83.         gHandleDiskRemovedUPP = NewNMProc(HandleDiskWasRemovedEvent);
  84.     }
  85.     
  86.     if ( gDisplayNotificationDlogUPP == nil )
  87.     {
  88.         gDisplayNotificationDlogUPP = NewNMProc(ActualDisplayNotifcationDialog);
  89.     }
  90.     
  91.     if ( gEjectDialogFilterUPP == nil )
  92.     {
  93.         gEjectDialogFilterUPP = NewModalFilterProc( EjectDialogFilterProc );
  94.     }
  95.  
  96.     return true;
  97. }
  98.  
  99. // This routine is used to release memory used by the driver info structure
  100. Boolean TerminateStorageDriverServices( void )
  101. {
  102.     ReleaseDialogResources();
  103.     
  104.     if ( gHandleDiskRemovedUPP != nil )
  105.     {
  106.         DisposeRoutineDescriptor( gHandleDiskRemovedUPP );
  107.         gHandleDiskRemovedUPP = nil;
  108.     }
  109.     
  110.     if ( gDisplayNotificationDlogUPP != nil )
  111.     {
  112.         DisposeRoutineDescriptor( gDisplayNotificationDlogUPP );
  113.         gDisplayNotificationDlogUPP = nil;
  114.     }
  115.  
  116.     if ( gEjectDialogFilterUPP != nil )
  117.     {
  118.         DisposeRoutineDescriptor( gEjectDialogFilterUPP );
  119.         gEjectDialogFilterUPP = nil;
  120.     }
  121.  
  122.     if ( appearLibID != 0 )
  123.     {
  124.         CloseConnection( &appearLibID );
  125.         appearLibID = 0;
  126.     }
  127.     
  128.     return true;
  129. }
  130.  
  131. typedef pascal OSErr (AutoSizeDialogProc) ( DialogPtr inDialog );
  132. typedef AutoSizeDialogProc *AutoSizeDialogProcPtr;
  133.  
  134. typedef pascal OSErr (StandardAlertProc) (AlertType inAlertType, unsigned char const *inError, unsigned char const *inExplanation,
  135.                                              const struct AlertStdAlertParamRec *inAlertParam, SInt16 *outItemHit);
  136. typedef StandardAlertProc *StandardAlertProcPtr;
  137.  
  138. typedef pascal OSErr (GetDialogItemAsControlProc) ( DialogPtr inDialog, SInt16 inItemNo,  ControlHandle *outControl);
  139. typedef GetDialogItemAsControlProc *GetDialogItemAsControlProcPtr;
  140.  
  141. static AutoSizeDialogProcPtr            myAutoSizeDialogProcPtr;
  142. static StandardAlertProcPtr                myStandardAlertProcPtr;
  143. static GetDialogItemAsControlProcPtr    myGetDialogItemAsControlProcPtr;
  144.  
  145. Boolean IsAppearancePresent( void )
  146. {
  147.     if ( gAppearanceIsPresent == false )
  148.     {
  149.         if ( StandardAlert == nil )
  150.         {
  151.             OSStatus            err;
  152.             Str255                errMessage;
  153.             CFragSymbolClass    symClass;
  154.             void                (*entryPoint)();
  155.             THz                    currentZone;
  156.             
  157.             currentZone = GetZone ();
  158.             SetZone ( SystemZone() );
  159.  
  160.             // We're not linked with AppearanceLib, so find it at runtime.
  161.             err = GetSharedLibrary ("\pAppearanceLib", kPowerPCCFragArch, kLoadCFrag, &appearLibID, (Ptr *)&entryPoint, errMessage);
  162.             if (err != noErr) 
  163.             {
  164.                 SetZone (currentZone);
  165.                 return false;
  166.             }
  167.             
  168.             err = FindSymbol (appearLibID, "\pStandardAlert", (Ptr *)&myStandardAlertProcPtr, &symClass);
  169.             if (err != noErr) 
  170.             {
  171.                 SetZone (currentZone);
  172.                 return false;
  173.             }
  174.             
  175.             err = FindSymbol (appearLibID, "\pAutoSizeDialog", (Ptr *)&myAutoSizeDialogProcPtr, &symClass);
  176.             if (err != noErr) 
  177.             {
  178.                 SetZone (currentZone);
  179.                 return false;
  180.             }
  181.             
  182.             err = FindSymbol (appearLibID, "\pGetDialogItemAsControl", (Ptr *)&myGetDialogItemAsControlProcPtr, &symClass);
  183.             if (err != noErr) 
  184.             {
  185.                 SetZone (currentZone);
  186.                 return false;
  187.             }
  188.             
  189.             SetZone (currentZone);
  190.             LoadDialogResources();
  191.             gAppearanceIsPresent = true;
  192.         }
  193.         else
  194.         {
  195.             // Set our Procedure pointers to the linked in functions
  196.             myStandardAlertProcPtr = StandardAlert;
  197.             myAutoSizeDialogProcPtr = AutoSizeDialog;
  198.             myGetDialogItemAsControlProcPtr = GetDialogItemAsControl;
  199.  
  200.             LoadDialogResources();
  201.             gAppearanceIsPresent = true;
  202.         }
  203.     }
  204.     
  205.     return gAppearanceIsPresent;
  206. }
  207.  
  208. // This routine is used by the shim to preload its dialog resources
  209. Boolean LoadDialogResources( void )
  210. {
  211.     short    myResFile;
  212.     THz        currentZone;
  213.     short    oldResFileID = 0;
  214.     short    dlogRezNum = DIALOG_REZ_NUMBER;
  215.  
  216.     // Get and detach the STR# resource into the system
  217.     // Set the following structures to point to the strings
  218.     SetResLoad(true);
  219.     
  220.     oldResFileID = CurResFile();                                    // get the current resource file ID
  221.     myResFile = OpenShimResourceFork();
  222.  
  223.     GetIndString(EjectFloppyStrings.string1, dlogRezNum, 1);
  224.     GetIndString(EjectFloppyStrings.string2, dlogRezNum, 2);
  225.     GetIndString(EjectFloppyStrings.string3, dlogRezNum, 3);
  226.     GetIndString(EjectCartridgeStrings.string1, dlogRezNum, 4);
  227.     GetIndString(EjectCartridgeStrings.string2, dlogRezNum, 5);
  228.     GetIndString(EjectCartridgeStrings.string3, dlogRezNum, 6);
  229.     GetIndString(ReinsertFloppyStrings.string1, dlogRezNum, 7);
  230.     GetIndString(ReinsertFloppyStrings.string2, dlogRezNum, 8);
  231.     GetIndString(ReinsertFloppyStrings.string3, dlogRezNum, 9);
  232.     GetIndString(ReinsertCartridgeStrings.string1, dlogRezNum, 10);
  233.     GetIndString(ReinsertCartridgeStrings.string2, dlogRezNum, 11);
  234.     GetIndString(ReinsertCartridgeStrings.string3, dlogRezNum, 12);
  235.     GetIndString(ReattachDeviceStrings.string1, dlogRezNum, 13);
  236.     GetIndString(ReattachDeviceStrings.string2, dlogRezNum, 14);
  237.     GetIndString(ReattachDeviceStrings.string3, dlogRezNum, 15);
  238.     GetIndString(ReattachDeviceHardDiskString3, dlogRezNum, 16);
  239.     GetIndString(CartridgeProtectedStrings.string1, dlogRezNum, 17);
  240.     GetIndString(CartridgeProtectedStrings.string2, dlogRezNum, 18);
  241.     GetIndString(CartridgeProtectedStrings.string3, dlogRezNum, 19);
  242.  
  243.     CloseShimResourceFork();
  244.     UseResFile(oldResFileID);                                        // point at the original file
  245.     return true;
  246. }
  247.  
  248. // This routine is used by the shim to release its dialog resources
  249. Boolean ReleaseDialogResources( void )
  250. {
  251.     // There currently are no dialog resources that need to be released.
  252.     return true;
  253. }
  254.  
  255. StorageClassShimDispatchTablePtr    GetShimDispatchTablePtr( void )
  256. {
  257.     return &gShimDispatchTable;
  258. }
  259.  
  260. DriverInfoPtr GetDriverInfoHeadPtr( void )
  261. {
  262.     return DriverInfoHeadPtr;
  263. }
  264.  
  265. DriverInfoPtr FindDriverInfoByDrvrRef( DriverRefNum    drvrRefNum )
  266. {
  267.     DriverInfoPtr    currentDriverInfoPtr;
  268.     
  269.     currentDriverInfoPtr = DriverInfoHeadPtr;
  270.     while(currentDriverInfoPtr != nil )
  271.     {
  272.         if(currentDriverInfoPtr->drvrRefNum == drvrRefNum)
  273.         {
  274.             break;
  275.         }
  276.         
  277.         currentDriverInfoPtr = currentDriverInfoPtr->nextDriverInfo;
  278.     }
  279.     
  280.     return currentDriverInfoPtr;
  281. }
  282.  
  283. DriverInfoPtr FindDriverInfoByUSBDeviceRef( USBDeviceRef usbDeviceRef )
  284. {
  285.     DriverInfoPtr    currentDriverInfoPtr;
  286.     
  287.     currentDriverInfoPtr = DriverInfoHeadPtr;
  288.     while(currentDriverInfoPtr != nil )
  289.     {
  290.         if(currentDriverInfoPtr->usbDeviceRef == usbDeviceRef)
  291.         {
  292.             break;
  293.         }
  294.         
  295.         currentDriverInfoPtr = currentDriverInfoPtr->nextDriverInfo;
  296.     }
  297.     
  298.     return currentDriverInfoPtr;
  299. }
  300.  
  301. DriverInfoPtr AddDriverInfoPtr( void )
  302. {
  303.     DriverInfoPtr    newDriverInfoPtr;
  304.  
  305.     newDriverInfoPtr = (DriverInfoPtr) PoolAllocateResident(sizeof(DriverInfo), true);
  306.         
  307.     if ( newDriverInfoPtr == nil )
  308.     {
  309.         return nil;
  310.     }
  311.     
  312.     // Check if this is the first element that we are creating    
  313.     if ( DriverInfoHeadPtr == nil )
  314.     {
  315.         // This is the first element, set the head and tail
  316.         // pointers to this element
  317.         DriverInfoHeadPtr = newDriverInfoPtr;
  318.         DriverInfoTailPtr = newDriverInfoPtr;
  319.     }
  320.     else
  321.     {
  322.         // This is not the first pointer, set the last element
  323.         // to point to this one, and set the tail pointer to this one
  324.         DriverInfoTailPtr->nextDriverInfo = newDriverInfoPtr;
  325.         DriverInfoTailPtr = newDriverInfoPtr;
  326.     }
  327.  
  328.     return newDriverInfoPtr;
  329. }
  330.  
  331. void RemoveDriverInfoPtr( DriverInfoPtr oldInfoPtr )
  332. {
  333.     OSStatus    status;
  334.     
  335.     if ( oldInfoPtr == nil )
  336.     {
  337.         return;
  338.     }
  339.     
  340.     // Check to see if the element being removed is the head element
  341.     if( DriverInfoHeadPtr == oldInfoPtr )
  342.     {
  343.         if ( DriverInfoTailPtr == oldInfoPtr )
  344.         {
  345.             // If the Head and Tail points to the element being
  346.             // removed, then it must be the only element.  Clear out the Head and Tail pointers
  347.             DriverInfoHeadPtr = nil;
  348.             DriverInfoTailPtr = nil;
  349.         }
  350.         else
  351.         {
  352.             // This is not the only element, set the head to the next element
  353.             DriverInfoHeadPtr = oldInfoPtr->nextDriverInfo;
  354.         }
  355.     }
  356.     else
  357.     {
  358.         // The element being removed is in the middle or end of the list,
  359.         // find the element before it
  360.         DriverInfoPtr currentDriverInfoPtr = DriverInfoHeadPtr;
  361.         
  362.         while ( currentDriverInfoPtr->nextDriverInfo != oldInfoPtr )
  363.         {
  364.             currentDriverInfoPtr = currentDriverInfoPtr->nextDriverInfo;
  365.         }
  366.         
  367.         // We couldn't find the element we are removing in the list, we
  368.         // could have been given a bad pointer. We can't do anything, so just leave.
  369.         if ( currentDriverInfoPtr == nil )
  370.         {
  371.             return;
  372.         }
  373.         
  374.         currentDriverInfoPtr->nextDriverInfo = oldInfoPtr->nextDriverInfo;
  375.         if (DriverInfoTailPtr == oldInfoPtr)
  376.         {
  377.             // If the element being removed is the tail element, update the tail
  378.             // to point to the previous element.
  379.             DriverInfoTailPtr = currentDriverInfoPtr;
  380.         }
  381.     }
  382.     
  383.     // Release the memory for the element
  384.     status = PoolDeallocate( oldInfoPtr );
  385. }
  386.  
  387. /******************************** Unit Table Driver Support Functions ******************************************/
  388. // This routine will initialize a Unit Table Infostructure to be passed to a driver
  389. void InitializeDriverInfoStruct( void )
  390. {
  391. }
  392.  
  393. // This is the routine that Unit Table drivers call to have the shim put up dialogs to notify the user that action is required
  394. // The following Notifications are needed:
  395. // 1) User needs to eject a manually eject floppy
  396. // 2) The user has removed a manual eject floppy while it was still in use
  397. // 3) a way for the driver to state a specific message
  398. // 4) possibly a way for a user to specify a dialog resource and a dialog function 
  399.  
  400. static Boolean removeDialog = false;
  401.  
  402. OSStatus HandleStorageEvent( DriverRefNum drvrRefNum, UInt16 messageNumber )
  403. {
  404.     DriverInfoPtr    driverInfoPtr;
  405.     OSStatus         status;
  406.     
  407.     driverInfoPtr = FindDriverInfoByDrvrRef( drvrRefNum );
  408.  
  409.     if ( messageNumber == kUSBStorageEventManualEjectMediaWasRemoved )
  410.     {
  411.         // Be sure to save the message number for the dialog
  412.         driverInfoPtr->messageNumber = messageNumber;
  413.         
  414.         BlockZero(&driverInfoPtr->theAlertNMRec, sizeof(NMRec));
  415.         driverInfoPtr->theAlertNMRec.qType = nmType;
  416.         driverInfoPtr->theAlertNMRec.nmSound = nil;
  417.         driverInfoPtr->theAlertNMRec.nmRefCon = (UInt32) drvrRefNum; // Save the driver ref for the completion routine
  418.         driverInfoPtr->theAlertNMRec.nmStr = nil;
  419.         driverInfoPtr->theAlertNMRec.nmResp = gHandleDiskRemovedUPP;
  420.         status = NMInstall( &driverInfoPtr->theAlertNMRec );
  421.     }
  422.     else
  423.     {
  424.         status = DisplayNotifcationDialog( drvrRefNum, messageNumber );
  425.     }
  426.     
  427.     return status;
  428. }
  429.  
  430. void HandleDiskWasRemovedEvent( NMRecPtr theNMRecPtr )
  431. {
  432.     DriverInfoPtr        driverInfoPtr;
  433.     DriverRefNum        drvrRefNum;
  434.     VCBPtr                 vol;
  435.     Boolean             allWereUnmounted = true;
  436.     OSStatus            theErr;
  437.     
  438.     // Remove our notification, ignore the result.
  439.     (void) NMRemove( theNMRecPtr );
  440.     drvrRefNum = (DriverRefNum) (theNMRecPtr->nmRefCon);
  441.     driverInfoPtr = FindDriverInfoByDrvrRef( drvrRefNum );
  442.     
  443.     if (driverInfoPtr == nil )
  444.     {
  445.         return;
  446.     }
  447.  
  448.     vol = (VCBPtr) (GetVCBQHdr())->qHead;
  449.     
  450.     while (vol)
  451.     {
  452.         // Check to see if this volume belongs to the driver
  453.         // that is being removed
  454.         if( vol->vcbDRefNum == driverInfoPtr->drvrRefNum)
  455.         {
  456.             short        driveNum;
  457.             
  458.             driveNum = vol->vcbDrvNum;
  459.             theErr = UnmountVol( nil, vol->vcbVRefNum );
  460.             Eject( nil, driveNum );
  461.  
  462.             // Check if unmount volume returns a file busy err.
  463.             if ((theErr == fBsyErr) || (theErr == ioErr))
  464.             {
  465.                 allWereUnmounted = false;
  466.             }
  467.         }
  468.         
  469.         vol = (VCBPtr) vol->qLink;
  470.     }
  471.     
  472.     if ( allWereUnmounted == false )
  473.     {
  474.         theErr = DisplayNotifcationDialog( drvrRefNum, kUSBStorageEventManualEjectMediaWasRemoved );
  475.     }
  476. }
  477.  
  478. OSStatus DisplayNotifcationDialog( DriverRefNum drvrRefNum, UInt16 messageNumber )
  479. {
  480.     OSStatus         status;
  481.     DriverInfoPtr    driverInfoPtr;
  482.  
  483.     driverInfoPtr = FindDriverInfoByDrvrRef( drvrRefNum );
  484.  
  485.     // Be sure to save the message number for the dialog
  486.     driverInfoPtr->messageNumber = messageNumber;
  487.     
  488.     BlockZero(&driverInfoPtr->theAlertNMRec, sizeof(NMRec));
  489.     driverInfoPtr->theAlertNMRec.qType = nmType;
  490.     driverInfoPtr->theAlertNMRec.nmSound = (Handle) -1;
  491.     driverInfoPtr->theAlertNMRec.nmRefCon = (UInt32) drvrRefNum; // Save the driver ref for the completion routine
  492.     
  493.     driverInfoPtr->theAlertNMRec.nmStr = nil;
  494.     driverInfoPtr->theAlertNMRec.nmResp = gDisplayNotificationDlogUPP;
  495.  
  496.     driverInfoPtr->hasDialog = true;
  497.     status = NMInstall( &driverInfoPtr->theAlertNMRec );
  498.     return status;
  499. }
  500.  
  501. // This is the routine that Unit Table drivers call to notify the shim that the action necessary has occurred and the dialog
  502. // needs to be removed.
  503. OSStatus RemoveNotificationDialog( DriverRefNum drvrRefNum, UInt16 messageNumber )
  504. {
  505. #pragma unused ( messageNumber )
  506.     DriverInfoPtr    driverInfoPtr;
  507.     OSStatus        status;
  508.  
  509.     driverInfoPtr = FindDriverInfoByDrvrRef( drvrRefNum );
  510.     if( driverInfoPtr != nil )
  511.     {
  512.         status = NMRemove( &driverInfoPtr->theAlertNMRec );
  513.         removeDialog = true;
  514.         driverInfoPtr->hasDialog = false;    
  515.     }
  516.     
  517.     return noErr;
  518. }
  519.  
  520. // Appearance Manager Savvy Dialog routines
  521. Boolean EjectDialogFilterProc(DialogPtr theDialog, EventRecord *theEvent, DialogItemIndex *itemHit)
  522. {
  523.     if(  removeDialog == true )
  524.     {
  525.         *itemHit = kAlertStdAlertOKButton;
  526.         return true;
  527.     }
  528.     else
  529.     {    
  530.         return StdFilterProc(theDialog, theEvent, itemHit);
  531.     }
  532. }
  533.  
  534. void ActualDisplayNotifcationDialog( NMRecPtr theNMRecPtr )
  535. {
  536.     SInt16                    itemHit;
  537.     DriverInfoPtr            driverInfoPtr;
  538.     DriverRefNum            drvrRefNum;
  539.     ShimDialogStringsPtr    theDialogStringsPtr;
  540.     AlertType                theAlertType;
  541.     Str255                     alertAStr;
  542.     Str255                     alertBStr;
  543.     
  544.     // Remove our notification, ignore the result.
  545.     (void) NMRemove( theNMRecPtr );
  546.     drvrRefNum = (DriverRefNum) (theNMRecPtr->nmRefCon);
  547.     driverInfoPtr = FindDriverInfoByDrvrRef( drvrRefNum );
  548.     
  549.     if (driverInfoPtr == nil )
  550.     {
  551.         return;
  552.     }
  553.  
  554.     if ( IsAppearancePresent() == false )
  555.     {
  556.         return;
  557.     }
  558.  
  559.     // Reattach Drive Dialogs
  560.     removeDialog = false;
  561.  
  562.     driverInfoPtr->theAlertPR.movable         = false;    // We do not want the alerts movable.    
  563.     driverInfoPtr->theAlertPR.helpButton     = false;    // Currently there is no associated help, so do not show a help button
  564.     driverInfoPtr->theAlertPR.filterProc     = gEjectDialogFilterUPP;
  565.     driverInfoPtr->theAlertPR.defaultText     = nil;         // Do not show an OK button on Stop Alerts
  566.     driverInfoPtr->theAlertPR.cancelText     = nil;         // Do not show a Cancel button on any Alert
  567.     driverInfoPtr->theAlertPR.otherText     = nil;         // Do not show a third button on any Alert
  568.     driverInfoPtr->theAlertPR.defaultButton = 0;         // set to nil for none
  569.     driverInfoPtr->theAlertPR.defaultButton = kAlertStdAlertOKButton; // Currently it seems Appearance doesn't like this set to zero
  570.     driverInfoPtr->theAlertPR.cancelButton     = 0;         // We do not have a Cancel button
  571.     driverInfoPtr->theAlertPR.position         = kWindowDefaultPosition; // Show in the default position
  572.  
  573.     switch ( driverInfoPtr->messageNumber ) 
  574.     {
  575.         case kUSBStorageEventRemoveManualEjectMedia:
  576.         {
  577.             if ( (driverInfoPtr->usbSubClass == kUSBStorageUFISubclass) || (driverInfoPtr->usbSubClass == kUSBStorageSFF8070iSubclass))
  578.             {
  579.                 theDialogStringsPtr = &EjectFloppyStrings;
  580.             }
  581.             else
  582.             {
  583.                 theDialogStringsPtr = &EjectCartridgeStrings;
  584.             }
  585.  
  586.             driverInfoPtr->theAlertPR.defaultText     = (unsigned char *) -1;     // Use the default OK text
  587.             driverInfoPtr->theAlertPR.defaultButton = kAlertStdAlertOKButton;     // Use the standard OK button
  588.             theAlertType = kAlertNoteAlert;
  589.         }
  590.         break;
  591.  
  592.         case kUSBStorageEventManualEjectMediaWasRemoved:
  593.         {
  594.             if ( (driverInfoPtr->usbSubClass == kUSBStorageUFISubclass) || (driverInfoPtr->usbSubClass == kUSBStorageSFF8070iSubclass))
  595.             {
  596.                 theDialogStringsPtr = &ReinsertFloppyStrings;
  597.             }
  598.             else
  599.             {
  600.                 theDialogStringsPtr = &ReinsertCartridgeStrings;
  601.             }
  602.             
  603.             theAlertType = kAlertStopAlert;
  604.         }
  605.         break;
  606.  
  607.         case kUSBStorageEventDeviceWasRemoved:
  608.         {
  609.             theAlertType = kAlertStopAlert;
  610.             theDialogStringsPtr = &ReattachDeviceStrings;
  611.         }
  612.         break;
  613.  
  614.         case kUSBStorageEventUnusableMediaEjected:
  615.         {
  616.             driverInfoPtr->theAlertPR.defaultText     = (unsigned char *) -1;     // Use the default OK text
  617.             driverInfoPtr->theAlertPR.defaultButton = kAlertStdAlertOKButton;     // Use the standard OK button
  618.             theAlertType = kAlertNoteAlert;
  619.             theDialogStringsPtr = &CartridgeProtectedStrings;
  620.         }
  621.         break;
  622.     }    
  623.  
  624.     PStrCopy(alertAStr,theDialogStringsPtr->string1);
  625.     PStrCat(alertAStr,driverInfoPtr->VendorProductStr);
  626.     PStrCat(alertAStr,theDialogStringsPtr->string2);
  627.     PStrCopy(alertBStr,theDialogStringsPtr->string3);
  628.     if ( theAlertType == kAlertNoteAlert)
  629.     {
  630.         // Since it is a NoteAlert, we can use the StandardAlert function to display the dialog
  631.         myStandardAlertProcPtr(theAlertType, alertAStr, alertBStr, &driverInfoPtr->theAlertPR, &itemHit);
  632.     }
  633.     else
  634.     {
  635.         // It is a StopAlert, we must set up our own dialog and display it
  636.         ControlHandle    currentItemHand;
  637.         short            itemHit;
  638.         DialogPtr        stopDialogPtr;
  639.         short            myResFile;
  640.         THz                currentZone;
  641.         short            oldResFileID = 0;
  642.         short            dlogRezNum = DIALOG_REZ_NUMBER;
  643.     
  644.         // Set the following structures to point to the strings
  645.         SetResLoad(true);
  646.         oldResFileID = CurResFile();                                    // get the current resource file ID
  647.         
  648.         myResFile = OpenShimResourceFork();
  649.         stopDialogPtr = GetNewDialog(dlogRezNum, nil, (WindowPtr) -1L );
  650.         if ( stopDialogPtr != nil )
  651.         {
  652.             myGetDialogItemAsControlProcPtr( stopDialogPtr, 2, ¤tItemHand );
  653.             SetDialogItemText( (Handle) currentItemHand, alertAStr );
  654.             myGetDialogItemAsControlProcPtr(stopDialogPtr, 3, ¤tItemHand);
  655.             SetDialogItemText( (Handle) currentItemHand, alertBStr );
  656.             myAutoSizeDialogProcPtr(stopDialogPtr);
  657.             ShowWindow(stopDialogPtr);
  658.             ModalDialog( gEjectDialogFilterUPP, &itemHit );
  659.             CloseWindow( stopDialogPtr );
  660.             DisposeWindow( stopDialogPtr );
  661.         }
  662.  
  663.         UseResFile(oldResFileID);                                        // point at the original file
  664.         CloseShimResourceFork();
  665.     }
  666. }
  667.